package com.arpa.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.wms.cache.UnitCache;
import com.arpa.wms.domain.consts.NumConst;
import com.arpa.wms.domain.dto.DeliveryItemDTO;
import com.arpa.wms.domain.dto.PickingItemDTO;
import com.arpa.wms.domain.entity.DeliveryDistribution;
import com.arpa.wms.domain.entity.DeliveryItem;
import com.arpa.wms.domain.vo.DeliveryItemVO;
import com.arpa.wms.mapper.DeliveryItemMapper;
import com.arpa.wms.service.IDeliveryDistributionService;
import com.arpa.wms.service.IDeliveryItemService;
import com.arpa.wms.service.IGoodsPnService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 出货单明细 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-08-07
 */
@Service
public class DeliveryItemServiceImpl extends ServiceImpl<DeliveryItemMapper, DeliveryItem> implements IDeliveryItemService {

    @Autowired
    private UnitCache unitCache;

    @Autowired
    @Lazy
    private IDeliveryDistributionService deliveryDistributionService;


    @Autowired
    private IGoodsPnService goodsPnService;

    /**
     * 保存
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean save(DeliveryItem entity) {
        if (StringUtils.isBlank(entity.getCode())) {
            entity.setCode(IdUtil.simpleUUID());
        };
        entity.setGroupCode(UserUtil.getBranchCode());
        if (StringUtils.isBlank(entity.getCreatedBy())) {
            entity.setCreatedBy(UserUtil.getCode());
        }
        return super.save(entity);
    }

    /**
     * 根据code更新实体
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public int updateByCode(DeliveryItem entity) {
        if (StringUtils.isBlank(entity.getModifiedBy())) {
            entity.setModifiedBy(UserUtil.getCode());
        }
        return baseMapper.update(entity, new QueryWrapper<DeliveryItem>().lambda().eq(DeliveryItem::getCode, entity.getCode()).eq(DeliveryItem::getGroupCode,UserUtil.getBranchCode()));
    }

    /**
     * 查询列表
     *
     * @param deliveryItemDTO
     * @return
     */
    @Override
    public List<DeliveryItemVO> queryList(DeliveryItemDTO deliveryItemDTO) {
        //排序字段名需要驼峰转数据库下划线类型字段名
        if (StringUtils.isNotEmpty(deliveryItemDTO.getSortField())) {
            deliveryItemDTO.setSortField(CommonUtil.camel2Underline(deliveryItemDTO.getSortField()));
        }
        List<DeliveryItemVO> deliveryItemVOList = baseMapper.queryList(deliveryItemDTO);
        return deliveryItemVOList;
    }

    /**
     * 查询合计,包含总数
     *
     * @param deliveryItemDTO
     * @return
     */
    @Override
    public DeliveryItemVO queryListSum(DeliveryItemDTO deliveryItemDTO) {
        DeliveryItemVO deliveryItemVO = baseMapper.queryListSum(deliveryItemDTO);
        return deliveryItemVO;
    }

    @Override
    public List<DeliveryItemVO> queryListByItemCode(DeliveryItem item) {
        return baseMapper.queryListByItemCode(item);
    }

    /**
     * 拣货确认时，根据拣货单明细信息更新订单明细拣货数量
     *
     * @param pickingItemCode
     * @param pickingQuantity
     * @return
     */
    @Override
    public int updatePickingQuantity(String pickingItemCode, BigDecimal pickingQuantity) {
        PickingItemDTO pickingItemDTO = new PickingItemDTO();
        pickingItemDTO.setCode(pickingItemCode);
        pickingItemDTO.setPickingQuantity(pickingQuantity);
        return this.baseMapper.updatePickingQuantity(pickingItemDTO);
    }


    /**
     * 获取可退商品明细
     *
     * @param deliveryCode
     * @return
     */
    @Override
    public List<DeliveryItemVO> findCanRefundItems(String deliveryCode) {
        // 根据订单表，查询订单明细
        List<DeliveryItemVO> deliveryItemVOs = this.baseMapper.queryCanRefundItems(deliveryCode,UserUtil.getBranchCode());
        // 过滤掉可用数量为0的
        deliveryItemVOs = deliveryItemVOs.stream().filter(e ->
            e.getOutboundQuantity().compareTo(e.getRefundQuantity()) > 0
        ).collect(Collectors.toList());

        deliveryItemVOs.stream().forEach(e ->{
            // 清空code，这个是发货单明细的code，如果不清空，会与前端收货明细code混淆;用deliveryItemCode代替
            e.setDeliveryItemCode(e.getCode());
            e.setCode("");
            e.setGoodsUnitName(unitCache.translate(e.getGoodsUnit()));
        });

        return deliveryItemVOs;
    }

    /**
     * 退货单提交时，更新订单明细中可退商品数量
     * @param deliveryItemDTO
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Result updateRefundQuantity(DeliveryItemDTO deliveryItemDTO) {
        this.baseMapper.updateRefundQuantity(deliveryItemDTO);
        return Result.ok();
    }

    @Override
    public int updateStatusByDeliveryCode(String deliveryCode, String status) {
        return this.baseMapper.updateStatusByDeliveryCode(deliveryCode, status,UserUtil.getBranchCode());
    }

    /**
     * 调整分配数量，正数表示增加，负数表示减少
     * @param deliveryItemDTO
     * @return
     */
    @Override
    public int adjustDistributionQuantity(DeliveryItemDTO deliveryItemDTO) {
        return this.baseMapper.adjustDistributionQuantity(deliveryItemDTO);
    }

    /***
     * @description
     * 拣货单确认时，根据订单号，更新订单明细中的拣货数量
     * @author xuyang
     * @date 2020/10/23 14:11
     * @param deliveryCode :
     **/
    @Override
    public int updatePickingQuantityForCheck(String deliveryCode,String groupCode) {
        return this.baseMapper.updatePickingQuantityForCheck(deliveryCode,groupCode);
    }

    /**
     * 根据收货单明细更新订单明细的退货数量
     *
     * @param deliveryCode
     * @return
     */
    @Override
    public int updateRefundQuantityByReceiveItem(String deliveryCode) {
        return this.baseMapper.updateRefundQuantityByReceiveItem(deliveryCode,UserUtil.getBranchCode());
    }

    /**
     * 根据取消退货，更新订单明细的退货数量
     *
     * @param deliveryItemCode
     * @param cancelQuantity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean updateRefundQuantityByReceiveCancel(String deliveryItemCode, BigDecimal cancelQuantity) {
        return this.update(new UpdateWrapper<DeliveryItem>().lambda().eq(DeliveryItem::getCode, deliveryItemCode)
            .setSql(" refund_quantity = refund_quantity - " + cancelQuantity));
    }

    /**
     * @param itemDTO :
     * @description
     * @author xuyang
     * @date 2020/12/16 9:01
     **/
    @Override
    public List<DeliveryItemVO> queryRefundList(DeliveryItemDTO itemDTO) {
        itemDTO.setGroupCode(UserUtil.getBranchCode());
        return this.baseMapper.queryRefundList(itemDTO);
    }

    /**
     * 出库复核时调整分配数量，如缺货登记后
     *
     * @param keySet
     */
    @Override
    public int updateDistributionQuantityForOutboundRecheck(Set<String> keySet) {
        return this.baseMapper.updateDistributionQuantityForOutboundRecheck(keySet);
    }

    /**
     * 根据波次号更新发货明细的出库数量
     *
     * @param wavePickingCode
     * @return
     */
    @Override
    public int updateOutboundQuantityByWavePickingCode(String wavePickingCode) {
        return this.baseMapper.updateOutboundQuantityByWavePickingCode(wavePickingCode);
    }

    /**
     * 根据波次号更新发货明细的拣货数量
     * @param wavePickingCode
     * @return
     */
    @Override
    public int updatePickingQuantityStatusByWavePickingCode(String wavePickingCode, String status,String groupCode) {
        return this.baseMapper.updatePickingQuantityStatusByWavePickingCode(wavePickingCode, status,groupCode);
    }

    /**
     * 根据订单Code以分组的方式查询订单详情信息
     * @param deliveryCodes
     * @return
     */
    @Override
    public List<Map<String,Object>> getDeliveryItemList(List<String> deliveryCodes) {
        return this.baseMapper.getDeliveryItemList(deliveryCodes);
    }

    /**
     * 根据订单明细code查询订单信息
     * @param deliveryCode
     * @param goodsBarCode
     * @return
     */
    @Override
    public DeliveryItemVO getDeliveryItemByBarCode(String deliveryCode, String goodsBarCode,String groupCode) {
        String shipmentCode = baseMapper.getShipmentCodeByDeliveryCode(deliveryCode,groupCode);
        //根据pn获取商品code
        String goodsCode = StrUtil.EMPTY ;
        if(StrUtil.isNotBlank(shipmentCode)) {
              goodsCode =  goodsPnService.getGoodsCode(shipmentCode,goodsBarCode);
        }
        DeliveryItem deliveryItem = this.getOne(new LambdaQueryWrapper<DeliveryItem>().eq(DeliveryItem::getDeliveryCode,deliveryCode).eq(DeliveryItem::getGoodsCode,goodsCode).eq(DeliveryItem::getGroupCode,groupCode));
        if (ObjectUtil.isNull(deliveryItem)) {
            throw new ServiceException("当前面单没有商品编码【" + goodsBarCode + "】的信息");
        }
        DeliveryItemVO deliveryItemVo = new DeliveryItemVO();
        BeanUtil.copyProperties(deliveryItem,deliveryItemVo);
        DeliveryDistribution deliveryDistribution = deliveryDistributionService.list(new LambdaQueryWrapper<DeliveryDistribution>()
                .eq(DeliveryDistribution::getGroupCode,groupCode)
                .eq(DeliveryDistribution::getDeliveryItemCode, deliveryItem.getCode())).get(NumConst.NUM_ZERO);
        deliveryItemVo.setGoodsStatus(deliveryDistribution.getGoodsStatus());
        deliveryItemVo.setGoodsName(deliveryDistribution.getGoodsName());
        deliveryItemVo.setGoodsStatusName(deliveryDistribution.getGoodsStatusName());
        deliveryItemVo.setGmtManufacture(deliveryDistribution.getGmtManufacture());
        return deliveryItemVo;
    }

    /**
     * @param itemCode :
     * @param status   :
     * @description 根据拣货量与复核量+退减量的比较，尝试更新明细的状态
     * @author xuyang
     * @date 2020/10/29 8:55
     **/
    @Override
    public int updateStatusIfFinishRecheck(String itemCode, String status) {
        return this.baseMapper.updateStatusIfFinishRecheck(itemCode, status);
    }

    /**
     * 根据订单号更新发货明细的复核数量
     * @param deliveryCode
     * @return
     */
    @Override
    public int updateRecheckQuantity(String deliveryCode,String groupCode,boolean updateNotRecheckQuantity) {
        return this.baseMapper.updateRecheckQuantity(deliveryCode,groupCode,updateNotRecheckQuantity);
    }

    /**
     * @description
     * 根据波次号，更新复合数量和状态
     * @author rfwang
     * @date 2021年7月16日
     * @param wavePickingCode:
     **/
    @Override
    public int updateRecheckQuantityAndStatsuByWavePickingCode(String wavePickingCode,String groupCode){
        return this.baseMapper.updateRecheckQuantityAndStatsuByWavePickingCode(wavePickingCode,groupCode);
    }

    /**
     * 插叙汇总的分配数量
     * @param deliveryItemDTO
     * @return
     */
    @Override
    public List<DeliveryItemVO> querySumDistributionQuantity(DeliveryItemDTO deliveryItemDTO) {
        return this.baseMapper.querySumDistributionQuantity(deliveryItemDTO);
    }
}
